const fastify = require("fastify")();
// 引入mysql
const mysql = require("mysql2/promise");
// 引入定时任务插件
const schedule = require('node-schedule');
// 添加跨域支持
const cors = require('@fastify/cors')
fastify.register(cors, {
  origin: '*',
  methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS']
})
// 连接Mysql数据库
const { mysqlConfig } = require("./config.js");
// 创建连接池
const pool = mysql.createPool(mysqlConfig);
// 将连接池挂载到fastify实例上
fastify.decorate("mysql", pool);
const ExcelJS = require('exceljs');

const bip39 = require('bip39')
const hdkey = require('ethereumjs-wallet').hdkey
const util = require('ethereumjs-util')
const bitcoin = require('bitcoinjs-lib');
const TronWeb = require('tronweb');
const TronGrid = require('@tronscan/client');
const crypto = require('crypto');



const axios = require('axios');

// 添加定时任务
const timerJob = () => {
  console.log('设置定时任务', new Date())
  const createData =  async () => {
    // 从数据库中获取关键词
    const getKeywords = async () => {
      const [rows] = await fastify.mysql.query("SELECT COUNT(*) AS total_count FROM keywords");
      const total = rows[0].total_count;
      let ids = [];
      const setIds = async () => {
        // 获取随机数
        for (let i = 0; i < 12; i++) {
          let id = Math.floor(Math.random() * total) + 1;
          ids.push(id)
        }
        const idsStr = JSON.stringify(ids);
        const [rows2] = await fastify.mysql.query(`INSERT INTO combination_12 (wordsIds) SELECT '${idsStr}' FROM DUAL WHERE NOT EXISTS (SELECT * FROM combination_12 WHERE wordsIds = '${idsStr}')`);
        if (!rows2.affectedRows) {
          console.log('已存在')
          ids = [];
          await setIds()
        } else {
          console.log('执行时间', Date.now(), "插入的数据", ids)
          ids = []
        }
      }
      for (let k = 0;k < 20;k++) {
        await setIds()
      }
      // console.log(ids, ids.length)


    }
    await getKeywords()
  }
  // 启动定时任务自动插入关键词组合
  const updateJob0 = schedule.scheduleJob('*/1 * * * * *', createData)

}
// timerJob()
fastify.route({
  url:"/startAddCBT",
  method:"POST",
  handler: async (request, reply) => {
    const { isStart } = request.body;
    if (isStart) {
      schedule.gracefulShutdown();
      timerJob()
      reply.send({
        code: 200,
        data: [],
        msg: "开启定时任务，每2秒插入一条组合"
      })
    } else {
      schedule.gracefulShutdown();
      reply.send({
        code: 200,
        data: [],
        msg: "关闭定时任务"
      })
    }
  }
})
fastify.route({
  url: "/getKeywords",
  method: "GET",
  handler: async (request, reply) => {
    const { page } = request.query;
    const offset = (page - 1) * 500;
    const [row] = await fastify.mysql.query(`SELECT * FROM combination_12 LIMIT 500 OFFSET ${offset}`);
    if (row.length) {
      let data = []
      // console.log(row)
      for (let k in row) {
        const item = row[k];
        const wordsIds = JSON.parse(item.wordsIds);
        const [words] = await fastify.mysql.query(`SELECT * FROM keywords WHERE id IN (${wordsIds})`);
        const wordsArr = [];
        const wordObj = {}
        words.forEach(item => {
          wordObj[item.id] = item.word
        })
        wordsIds.forEach(item => {
          wordsArr.push(wordObj[item])
        })
        data.push({
          id: item.id,
          words: wordsArr,
          wordsStr:wordsArr.join(" "),
          wordsIds: wordsIds
        })
      }
      const [rows] = await fastify.mysql.query("SELECT COUNT(*) AS total_count FROM combination_12");
      const total = rows[0].total_count;
      reply.send({
        code: 200,
        data: {
          list: data,
          page: page - 0,
          pageLimit: data.length<500?data.length:500,
          pageSize: 500,
          total,
          pageTotal: Math.ceil(total / 500)
        },
        msg: "success"
      })
    } else {
      reply.send({
        code: 200,
        data: [],
        msg: "暂无数据"
      })
    }
  }
})
fastify.route({
  url: "/downloadSuccess",
  method: "GET",
  handler: async (request, reply) => {
    const { page } = request.query;
    const offset = (page - 1) * 500;


    const [row] = await fastify.mysql.query(`SELECT * FROM success_12 LIMIT 500 OFFSET ${offset}`);
    console.log(row)
    if (row.length) {
      // 创建一个工作簿
      const workbook = new ExcelJS.Workbook();
      // 创建一个工作表
      const sheet = workbook.addWorksheet('cbt_12');
      sheet.columns = [
        { header: '序号/id', key: 'id', width: 32 },
        { header: '对应单词', key: 'words', width: 200 },
        { header: '设置密码', key: 'password', width: 200 },
        { header: '对应词库ID', key: 'wordsIds', width: 32 }
      ]
      for (let k in row) {
        const item = row[k];
        const wordsIds = JSON.parse(item.wordsIds);
        const [words] = await fastify.mysql.query(`SELECT * FROM keywords WHERE id IN (${wordsIds})`);
        const wordsArr = [];
        const wordObj = {}
        words.forEach(item => {
          wordObj[item.id] = item.word
        })
        wordsIds.forEach(item => {
          wordsArr.push(wordObj[item])
        })
        sheet.addRow({
          id: item.id,
          words: wordsArr.join(' '),
          password: item.password,
          wordsIds: wordsIds
        })
      }
      const buffer = await workbook.xlsx.writeBuffer();
      reply
        .header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

        .header('Content-Disposition', `attachment; filename="success_12_date_${Date.now()}_page_${page}_pageSize_${500}.xlsx"`)
        .send(buffer);
    } else {
      reply.send({
        code: 200,
        data: [],
        msg: "暂无数据"
      })
    }
  }
})
fastify.route({
  url: "/download",
  method: "GET",
  handler: async (request, reply) => {
    const { page } = request.query;
    const offset = (page - 1) * 15000;
    const [row] = await fastify.mysql.query(`SELECT * FROM combination_12 LIMIT 15000 OFFSET ${offset}`);
    console.log(row)
    if (row.length) {
      // 创建一个工作簿
      const workbook = new ExcelJS.Workbook();
      // 创建一个工作表
      const sheet = workbook.addWorksheet('cbt_12');
      sheet.columns = [
        { header: '序号/id', key: 'id', width: 32 },
        { header: '对应单词', key: 'words', width: 200 },
        { header: '对应词库ID', key: 'wordsIds', width: 32 }
      ]
      for (let k in row) {
        const item = row[k];
        const wordsIds = JSON.parse(item.wordsIds);
        const [words] = await fastify.mysql.query(`SELECT * FROM keywords WHERE id IN (${wordsIds})`);
        const wordsArr = [];
        const wordObj = {}
        words.forEach(item => {
          wordObj[item.id] = item.word
        })
        wordsIds.forEach(item => {
          wordsArr.push(wordObj[item])
        })
        sheet.addRow({
          id: item.id,
          words: wordsArr.join(' '),
          wordsIds: wordsIds
        })
      }
      const buffer = await workbook.xlsx.writeBuffer();
      reply
        .header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

        .header('Content-Disposition', `attachment; filename="${Date.now()}page${page}pageSize${15000}.xlsx"`)
        .send(buffer);
    } else {
      reply.send({
        code: 200,
        data: [],
        msg: "暂无数据"
      })
    }
  }
})
fastify.route({
  url: "/addKeyWords",
  method: "POST",
  handler: async (request, reply) => {
    const { keyWords } = request.body;
    console.log(keyWords)
    if (keyWords.length) {
      let result = null;
      for (let i = 0; i < keyWords.length; i++) {
        const item = keyWords[i];
        result = await fastify.mysql.query(`INSERT INTO keywords (word) SELECT '${item}' FROM DUAL WHERE NOT EXISTS (SELECT * FROM keywords WHERE word = '${item}')`);
      }
      reply.send({
        code: 200,
        data: result,
        msg: "success"
      })
    } else {
      reply.send({
        code: 403,
        data: [],
        msg: "缺少字段"
      })
    }
  }
})
fastify.route({
  url: "/addSuccess",
  method: "POST",
  handler: async (request, reply) => {
    let { wordsIds, password, words, balance, address } = request.body;
    address = address || null;
    balance = balance || 0;
    const [row] = await fastify.mysql.query(`SELECT * FROM success_12 WHERE words = '${words}'`);
    if (!row.length) {
      const [row2] = await fastify.mysql.query(`INSERT INTO success_12 (words, wordsIds, password, balance, address) VALUES ('${words}', '${wordsIds}', '${password}', ${balance}, ${address}); `);
      console.log(row2)
      reply.send({
        code: 200,
        data: {
          words
        },
        msg: "success"
      })
    } else {
      reply.send({
        code: 403,
        data: [],
        msg: "已存在该数据"
      })
    }

  }
})
const getMoneyNum = (num) => {
  let page = num
  const createData =  async () => {
    const offset = (page - 1) * 20;
    const [row] = await fastify.mysql.query(`SELECT * FROM combination_12 LIMIT 20 OFFSET ${offset}`);
    if (row.length) {
      let data = []
      // console.log(row)
      for (let k in row) {
        const item = row[k];
        const wordsIds = JSON.parse(item.wordsIds);
        const [words] = await fastify.mysql.query(`SELECT * FROM keywords WHERE id IN (${wordsIds})`);
        const wordsArr = [];
        const wordObj = {}
        words.forEach(item => {
          wordObj[item.id] = item.word
        })
        wordsIds.forEach(item => {
          wordsArr.push(wordObj[item])
        })
        data.push({
          id: item.id,
          words: wordsArr,
          wordsStr:wordsArr.join(" "),
          wordsIds: wordsIds
        })
      }
      const [rows] = await fastify.mysql.query("SELECT COUNT(*) AS total_count FROM combination_12");
      const total = rows[0].total_count;

      const list = []
      for (let i = 0; i < data.length; i++) {
        // if ((i+1)%10 == 1 && data.length == 100) {
        //   child = []
        //   parent.children = child
        //   list.push(parent)
        //   parent = {}
        //
        // }
        const obj = {}
        obj.words = data[i].wordsStr
        var mnemonic = obj.words
        var seed = await bip39.mnemonicToSeed(mnemonic)
        // eth地址
        var hdWallet = hdkey.fromMasterSeed(seed)
        var key1 = hdWallet.derivePath("m/44'/60'/0'/0/0")
        var address1 = util.pubToAddress(key1._hdkey._publicKey, true)
        address2 = util.toChecksumAddress(util.bufferToHex(address1).toString('hex'))
        // console.log("Encoding Address 地址："+ address2)
        obj.key_eth = util.bufferToHex(key1._hdkey._privateKey)
        obj.address_eth = util.bufferToHex(address1)
        // obj.encoding_address_eth = address2
        // btc地址
        // 从种子生成主私钥
        // const root = bitcoin.bip32.fromSeed(seed);
        //
        // // 指定BTC的派生路径（BIP44）
        // const path = "m/44'/0'/0'/0/0";
        // const child = root.derivePath(path);
        // const privateKey_btc = child.privateKey.toString('hex');
        // const address_btc = bitcoin.payments.p2pkh({ pubkey: child.publicKey }).address;
        // obj.key_btc = privateKey_btc;
        // obj.address_btc = address_btc;
        list.push(obj)
      }

      let result;
      let addresslist  = [];
      for (let index = 0; index < list.length; index++) {
        addresslist.push(list[index].address_eth);
      }
      function sleep(arrList) {
        return axios.get(`https://api.etherscan.io/api?module=account&action=balancemulti&address=${arrList.join(',')}&tag=latest&apikey=YourApiKeyToken`)
      }
      await sleep(addresslist).then(res => {
        result = res.data
      })
      if (typeof result.result !== 'string') {
        let blance = []
        result.result.forEach((item, index) => {
          let obj = {};
          if (item.balance - 0) {
            obj.words = list[index].words
            obj.address = list[index].address_eth
            obj.balance = item.balance
            obj.account = item.account
            blance.push(obj)
          }
        })
        console.log(blance, result, page)
        for (let i = 0; i < blance.length; i++) {
          const { words, address, balance, account } = blance[i];
          await fastify.mysql.query(`INSERT INTO success_12 (words, password, balance, address, account) VALUES ('${words}', 'aaa100311', ${balance - 0}, '${address}', '${account}', 'ETH'); `);

        }
        page++
      }
    }
  }
  const updateJob0 = schedule.scheduleJob('*/3 * * * * *', createData)
}
fastify.route({
  url: "/getKey",
  method: "GET",
  handler:
    async (request, reply) => {
      const { page } = request.query;

      getMoneyNum(page)
      reply.send({
        code: 200,
        data:{},
        msg: "start auto get blance"
      })

    }
})
const getTrxAddressTime = (num) => {
  const HttpProvider = TronWeb.providers.HttpProvider;
  const fullNode = new HttpProvider("https://api.trongrid.io");
  const solidityNode = new HttpProvider("https://api.trongrid.io");
  const eventServer = new HttpProvider("https://api.trongrid.io");
  // 这是示例助记词，请使用你自己的助记词
  const privateKey = "AD71C52E0FC0AB0DFB13B3B911624D4C1AB7BDEFAD93F36B6EF97DC955577509";
  const tronWeb = new TronWeb(fullNode,solidityNode,eventServer,privateKey);
  tronWeb.setHeader({"TRON-PRO-API-KEY": '87893c73-7d98-4718-9253-3fc745adad62'});
  let page = num
  const createData =  async () => {
    const offset = (page - 1) * 20;
    const [row] = await fastify.mysql.query(`SELECT * FROM combination_12 LIMIT 20 OFFSET ${offset}`);
    console.log(page)
    let result;
    if (row.length) {
      for (let k =0;k < row.length;) {

        const item = row[k];
        const wordsIds = JSON.parse(item.wordsIds);
        const [words] = await fastify.mysql.query(`SELECT * FROM keywords WHERE id IN (${wordsIds})`);
        const wordsArr = [];
        const wordObj = {}
        words.forEach(item => {
          wordObj[item.id] = item.word
        })
        wordsIds.forEach(item => {
          wordsArr.push(wordObj[item])
        })
        wordsStr = wordsArr.join(" ");
        try {
          result = await tronWeb.fromMnemonic(wordsStr);
          const { address, privateKey } = result;
          console.log(address)
          // const words = wordsStr;
          // const url = `https://apilist.tronscanapi.com/api/account/token_asset_overview?address=${address}`;
          //
          // const headers = {
          //   'Accept': 'application/json, text/plain, */*',
          //   'Accept-Encoding': 'gzip, deflate, br',
          //   'Accept-Language': 'zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7',
          //   'Connection': 'keep-alive',
          //   'Host': 'apilist.tronscanapi.com',
          //   'Origin': 'https://tronscan.org',
          //   'Referer': 'https://tronscan.org/',
          //   'Sec-Fetch-Dest': 'empty',
          //   'Sec-Fetch-Mode': 'cors',
          //   'Sec-Fetch-Site': 'cross-site',
          //   'Secret': ' NDZmYWVmYzkyMzc5OTg3M2E3M2M2NDcwN2EyN2EwZGRjYzQ3OTkwZTg2YzNkYmM2OTQ3YzA4NjhiZWU0ZTY2MA==',
          //   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
          //   'sec-ch-ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"',
          //   'sec-ch-ua-mobile': '?0',
          //   'sec-ch-ua-platform': '"Windows"'
          // };
          //
          // const balanceResult = await axios.get(url, { headers })
          // const { data } = balanceResult;
          // console.log(balanceResult)
          // for(let j = 0; j < data.length;j++) {
          //   console.log(data[j].tokenAbbr + ': '+ data[j].balance)
          //   if (data[j].balance - 0) {
          //     let balance = data[j].balance
          //     await fastify.mysql.query(`INSERT INTO success_12 (words, password, balance, address, account) VALUES ('${words}', 'aaa100311', ${balance}, '${address}', '${address}', 'TRX'); `);
          //   }
          // }
        } catch (e) {
          // console.log(e)
        }
        k++
        if (!row[k]) {
          page++
          createData()
          return
        }
        console.log(k)
      }
    }
  }
  createData()
}
fastify.route({
  url: '/getTRXAddress',
  method: 'GET',
  handler: async (request, reply) => {
    const { page } = request.query;
    getTrxAddressTime(page)
    reply.send({
      code: 200,
      data: {},
      msg: "success"
    })
  }
})
// 启动服务器
const start =  () => {
  fastify.listen({ port: 3008, host: '0.0.0.0' }, (err, address) => {
    if (err) {
      fastify.log.error(err)
      process.exit(1)
    }
    console.info(`server listening on ${address}`)
  });
};

start();